package com.iris.live.services.report.data.timeline;

import com.iris.live.services.common.DateFormatUtils;
import com.iris.live.services.data.models.ReportConfig;
import com.iris.live.services.report.data.ReportDataConvertor;
import com.iris.live.services.report.data.formulars.FormularFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description:按照时间轴转换数据
 * @author: Tony.Zhang
 * @Date: 2017-08-11 11:28
 **/
@Component("TimelineConvertor")
public class TimelineConvertor extends ReportDataConvertor<TimelineContext> {
    private Logger logger = LoggerFactory.getLogger(TimelineConvertor.class);

    @Override
    protected void getFormularData(TimelineContext context, Map<String, Map> datas, Map reportRow, ReportConfig config) throws Exception {
        String fullPath = this.getFullPath(config), formularExpression = config.getFormularExpression();
        Map resultCell = null;
        String formular = formularExpression.substring(0, formularExpression.indexOf("("));
        List<TimeUnit> units = context.getTimeUnits();
        for(TimeUnit unit : units){ //按照用户设置的时间轴上的时间和当前时间进行比较并进行合计
            resultCell = (Map) reportRow.get(fullPath + "_" + unit.getValue());
            if (resultCell == null) {
                resultCell = new HashMap<>();
                resultCell.put("color", 1);
                resultCell.put("displayRow", unit.getText());
                resultCell.put("displayRowOrder", unit.getDisplayRowOrder());
                resultCell.put(config.getCategory() + "Value", 0);
            }

            Object value = getData(formular, config, unit, datas);

            this.setResultCell(resultCell, config, value);
            reportRow.put(fullPath + "_" + unit.getValue(), resultCell);
        }
    }

    /**
     * 从数据库获取报表数据
     * @param resultSet
     * @param config
     * @return
     * @throws Exception
     */
    @Override
    protected void getData(TimelineContext context, Map reportRow, Map resultSet, ReportConfig config) throws Exception{
        Map resultCell = null;
        String timeColumn = context.getTimeColumn(), timeValue = null, valueKey = config.getValueKey().trim(), fullPath = this.getFullPath(config);
        Object value = null;

        List<TimeUnit> units = context.getTimeUnits();
        if(config.isBlank()) {
            for (TimeUnit unit : units) {
                resultCell = (Map) reportRow.get(fullPath + "_" + unit.getValue());
                if (resultCell == null) {
                    resultCell = new HashMap<>();
                    resultCell.put("color", 0);
                    resultCell.put("displayRow", unit.getText());
                    resultCell.put("displayRowOrder", unit.getDisplayRowOrder());
                    resultCell.put(config.getCategory() + "Value", null);
                }
                reportRow.put(fullPath + "_" + unit.getValue(), resultCell);
            }
        }

        if(! resultSet.containsKey(timeColumn)){
            throw new Exception(String.format("数据集中查不到%s字段，不能按照时间轴进行数据转换", timeColumn));
        }

        timeValue = resultSet.get(timeColumn).toString();
        if(! resultSet.containsKey(valueKey)){
            resultCell = new HashMap();
            resultCell.put("color", 0);
            resultCell.put("displayRow", timeValue);
            this.setResultCell(resultCell, config, 0);

            return;
        }

        if(resultSet.get(valueKey) != null){
            value = resultSet.get(valueKey);
        }else{
            value = 0;
        }

        //计算当前时间累积
        resultCell = (Map)reportRow.get(fullPath + "_" + timeValue);
        if(resultCell == null){
            resultCell = new HashMap<>();
            resultCell.put("color", 0);
            resultCell.put("displayRow", timeValue);
            //这里添加最小统计维度（即月份的）的行序displayRowOrder
            List<TimeUnit> timeUnits = context.getTimeUnits();
            for (TimeUnit unit : timeUnits) {
                if (timeValue.equals(unit.getValue())) {
                    resultCell.put("displayRowOrder",unit.getDisplayRowOrder());
                }
            }
        }
        this.setResultCell(resultCell, config, value);
        reportRow.put(fullPath + "_"  + timeValue , resultCell);

        //处理累计
        TimeUnit currentUnit = null;
        for(TimeUnit unit : units){
            resultCell = (Map)reportRow.get(fullPath + "_" + unit.getValue());
            if(resultCell == null){
                resultCell = new HashMap<>();
                resultCell.put("color", 0);
                resultCell.put("displayRow", unit.getText());
                resultCell.put("displayRowOrder", unit.getDisplayRowOrder());
                resultCell.put(config.getCategory()+ "Value",Double.valueOf(0));
            }
            this.setResultCell(resultCell, config, 0);
            reportRow.put(fullPath + "_" + unit.getValue(), resultCell);

            if(unit.getValue().equals(timeValue)){
                currentUnit = unit;
                break;
            }
        }

        for(TimeUnit unit : units){
            Map rc = (Map)reportRow.get(fullPath + "_" + unit.getValue());
            if(rc == null){
                rc = new HashMap<>();
                rc.put("color", 0);
                rc.put("displayRow", unit.getValue());
                rc.put("displayRowOrder", unit.getDisplayRowOrder());
            }
            if(unit.getType().ordinal() < currentUnit.getType().ordinal()){
                switch(unit.getType()) {
                    case YEAR: //按年合计
                        rc = (Map) reportRow.get(fullPath + "_" + unit.getValue());
                        if (rc == null) {
                            rc = new HashMap<>();
                            rc.put("color", 0);
                            rc.put("displayRow", unit.getText());
                            rc.put("displayRowOrder", unit.getDisplayRowOrder());
                            rc.put(config.getCategory()+ "Value",0);
                        }
                        this.setResultCell(rc, config, value);
                        reportRow.put(fullPath + "_" + unit.getValue(), rc);
                        break;
                    case QUARTER: //按季度合计
                        String quarter = this.getQuarter(timeValue);
                        if (quarter.equals(unit.getValue())) { //仅当获取的季度和遍历中的季度匹配才累加
                            rc = (Map) reportRow.get(fullPath + "_" + quarter);
                            if (rc == null) {
                                rc = new HashMap<>();
                                rc.put("color", 0);
                                rc.put("displayRow", quarter);
                                rc.put("displayRowOrder", unit.getDisplayRowOrder());
                                rc.put(config.getCategory()+ "Value",0);
                            }
                            this.setResultCell(rc, config, value);
                            reportRow.put(fullPath + "_" + quarter, rc);
                        }
                        break;
                    case MONTH: ////按月份合计
                        String month = this.getMonth(timeValue);
                        rc = (Map) reportRow.get(fullPath + "_" + month);
                        if (rc == null) {
                            rc = new HashMap<>();
                            rc.put("color", 0);
                            rc.put("displayRow", unit.getValue());
                            rc.put("displayRowOrder", unit.getDisplayRowOrder());
                            rc.put(config.getCategory()+ "Value",0);
                        }
                        this.setResultCell(rc, config, value);
                        reportRow.put(fullPath + "_" + month, rc);
                        break;
                    case WEEK: //按周合计，目前没实现
                        throw new Exception("没有实现按周进行合计。");
                    }
            }else{
                this.setResultCell(rc, config, 0);
            }

            reportRow.put( fullPath+"_"+unit.getValue(), rc);
        }
    }



    /**
     * 获取timeValue所属季度
     * @param timeValue
     * @return
     * @throws Exception
     */
    private String getQuarter(String timeValue) throws Exception{
        String[] values = timeValue.split("-"), dateValue = null;
        if(values.length > 1){
            Date date = DateFormatUtils.getFormatDate(timeValue, DateFormatUtils.TIME_FORMAT_STR_YYYY_MM_DD);
            timeValue = DateFormatUtils.getFormatDateToString(date, "MM");
        }
        int month = Integer.parseInt(timeValue);
        if(month >= 1 && month <= 3){
            return "Q1";
        }else if(month >= 4 && month <= 6){
            return "Q2";
        }else if(month >= 7 && month <= 9){
            return "Q3";
        }else{
            return "Q4";
        }
    }

    /**
     * 获取timeValue所属月份
     * @param timeValue
     * @return
     * @throws Exception
     */
    private String getMonth(String timeValue) throws Exception{
        Date date = DateFormatUtils.getFormatDate(timeValue, DateFormatUtils.TIME_FORMAT_STR_YYYY_MM_DD);

        return DateFormatUtils.getFormatDateToString(date, "MM");
    }

    /**
     * 获取公式项值
     * @param formular
     * @param config
     * @param unit
     * @param datas
     * @return
     * @throws Exception
     */
    protected Double getData(String formular, ReportConfig config, TimeUnit unit, Map<String, Map> datas) throws Exception{
        return  FormularFactory.getFormular(formular).getValue(config, unit.getValue(), datas);
    }
}